/**************************************************************************************************
**                                                                                               **
**  文件名称:  dal_adc_drv.c                                                                     **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  ADC接口驱动                                                                       **
**  ===========================================================================================  **
**  创建信息:  | 2017-8-2 | LEON | 创建本模块                                                    **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "dal_include.h"
#include "dal_adc_drv.h"

/*************************************************************************************************/
/*                           定义模块数据结构                                                    */
/*************************************************************************************************/
typedef struct {
    INT8U    status;
    INT16U   valued[ADC_CH_MAX + 3];
} ADC_CTRL_T;

/*************************************************************************************************/
/*                           定义模块变量                                                        */
/*************************************************************************************************/
static ADC_CTRL_T  s_adcdcb;

/**************************************************************************************************
**  函数名称:  ADC_PINConfig
**  功能描述:  管脚配置
**  输入参数:  pinfo: 配置表
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ADC_PINConfig(const ADC_REG_T *pinfo)
{
    GPIO_InitTypeDef gpio_initstruct;
    
    if (pinfo == 0) {
        return;
    }
    
    gpio_initstruct.GPIO_Pin   = (INT16U)(1 << pinfo->pin_adc);
    gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_initstruct.GPIO_Mode  = GPIO_Mode_AN;
    gpio_initstruct.GPIO_OType = GPIO_OType_OD;
    gpio_initstruct.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    
    GPIO_Init((GPIO_TypeDef *)pinfo->gpio_base, &gpio_initstruct);
}

/**************************************************************************************************
**  函数名称:  ADC_DMAConfig
**  功能描述:  DMA配置
**  输入参数:  pinfo: 配置表
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ADC_DMAConfig(const ADC_REG_T *pinfo, BOOLEAN enable)
{
    DMA_InitTypeDef dma_initstruct;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, (enable == TRUE) ? ENABLE : DISABLE);
    
    DMA_DeInit((DMA_Channel_TypeDef *)pinfo->dma_base);
    
    if (enable == TRUE) {
        DMA_StructInit(&dma_initstruct);
        dma_initstruct.DMA_PeripheralBaseAddr = (INT32U)&(((ADC_TypeDef *)pinfo->adc_base)->DR);
        dma_initstruct.DMA_MemoryBaseAddr     = (INT32U)s_adcdcb.valued;
        dma_initstruct.DMA_DIR                = DMA_DIR_PeripheralSRC;
        dma_initstruct.DMA_BufferSize         = ADC_CH_MAX + 3;
        dma_initstruct.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
        dma_initstruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;
        dma_initstruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        dma_initstruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
        dma_initstruct.DMA_Mode               = DMA_Mode_Circular;
        dma_initstruct.DMA_Priority           = DMA_Priority_High;
        dma_initstruct.DMA_M2M                = DMA_M2M_Disable;
        
        DMA_Init((DMA_Channel_TypeDef *)pinfo->dma_base, &dma_initstruct);
    }
    
    DMA_Cmd(DMA1_Channel1, (enable == TRUE) ? ENABLE : DISABLE);
}

/**************************************************************************************************
**  函数名称:  ADC_ADCConfig
**  功能描述:  ADC配置
**  输入参数:  pinfo: 配置表
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ADC_ADCConfig(BOOLEAN enable)
{
    INT8U i, nreg;
    const ADC_REG_T *pinfo;
    ADC_InitTypeDef adc_initstructure;
    
    nreg = ST_ADC_GetCfgTblMax();
    
    if (nreg == 0) {
        return;
    }
    
    pinfo = ST_ADC_GetRegTblInfo(0);
    
    RCC_APB2PeriphClockCmd(pinfo->adc_rcc, (enable == TRUE) ? ENABLE : DISABLE);
    
    ADC_DeInit((ADC_TypeDef *)pinfo->adc_base);
    
    if (enable == FALSE) {
        ADC_TempSensorCmd(DISABLE);
        ADC_VrefintCmd(DISABLE);
        ADC_VbatCmd(DISABLE);
        return;
    }
    
    ADC_StructInit(&adc_initstructure);
    
    adc_initstructure.ADC_Resolution           = ADC_Resolution_12b;
    adc_initstructure.ADC_ContinuousConvMode   = ENABLE;
    adc_initstructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    adc_initstructure.ADC_DataAlign            = ADC_DataAlign_Right;
    adc_initstructure.ADC_ScanDirection        = ADC_ScanDirection_Upward;
    ADC_Init((ADC_TypeDef *)pinfo->adc_base, &adc_initstructure); 
    
    for (i = 0; i < nreg; i++) {
        pinfo = ST_ADC_GetRegTblInfo(i);
        ADC_PINConfig(pinfo);
        ADC_ChannelConfig((ADC_TypeDef *)pinfo->adc_base, pinfo->channel, ADC_SampleTime_55_5Cycles);
    }
    
    ADC_ChannelConfig((ADC_TypeDef *)pinfo->adc_base, ADC_Channel_TempSensor , ADC_SampleTime_55_5Cycles);  
    ADC_TempSensorCmd(ENABLE);
    
    ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles); 
    ADC_VrefintCmd(ENABLE);
    
    ADC_ChannelConfig(ADC1, ADC_Channel_Vbat , ADC_SampleTime_55_5Cycles);  
    ADC_VbatCmd(ENABLE);
}

/**************************************************************************************************
**  函数名称:  ADC_StartConvert
**  功能描述:  启动ADC采集功能
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ADC_StartConvert(void)
{
    INT8U nreg;
    INT32U ct_delay;
    const ADC_REG_T *pinfo;
    
    nreg = ST_ADC_GetCfgTblMax();
    
    if (nreg == 0) {
        return;
    }
    
    pinfo = ST_ADC_GetRegTblInfo(0);
    ADC_DMAConfig(pinfo, TRUE);
    ADC_ADCConfig(TRUE);
    
    ADC_GetCalibrationFactor((ADC_TypeDef *)pinfo->adc_base);
    ADC_DMARequestModeConfig((ADC_TypeDef *)pinfo->adc_base, ADC_DMAMode_Circular);
    ADC_DMACmd((ADC_TypeDef *)pinfo->adc_base, ENABLE);
    ADC_Cmd((ADC_TypeDef *)pinfo->adc_base, ENABLE);
    
    ct_delay = 0;
    while (++ct_delay < 0x1000) {
        if (ADC_GetFlagStatus((ADC_TypeDef *)pinfo->adc_base, ADC_FLAG_ADEN)) {
            break;
        }
    }
    
    SYS_ASSERT((ct_delay < 0x1000), RETURN_VOID);
    
    ADC_StartOfConversion((ADC_TypeDef *)pinfo->adc_base);
}

/**************************************************************************************************
**  函数名称:  ADC_StopConvert
**  功能描述:  停止ADC转换，并关闭整个功能
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ADC_StopConvert(void)
{
    INT8U nreg;
    const ADC_REG_T *pinfo;
    
    nreg = ST_ADC_GetCfgTblMax();
    
    if (nreg == 0) {
        return;
    }
    
    pinfo = ST_ADC_GetRegTblInfo(0);
    ADC_DMAConfig(pinfo, FALSE);
    ADC_ADCConfig(FALSE);
    
    ADC_StopOfConversion((ADC_TypeDef *)pinfo->adc_base);
    ADC_DMACmd((ADC_TypeDef *)pinfo->adc_base, DISABLE);
    ADC_Cmd((ADC_TypeDef *)pinfo->adc_base, DISABLE);
}

/**************************************************************************************************
**  函数名称:  DAL_ADC_Init
**  功能描述:  初始化模块
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void DAL_ADC_Init(void)
{
    YX_MEMSET(&s_adcdcb, 0, sizeof(s_adcdcb));
}

/**************************************************************************************************
**  函数名称:  DAL_ADC_Config
**  功能描述:  ADC功能开关
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void DAL_ADC_Config(BOOLEAN enable)
{
    if (enable == TRUE) {
        ADC_StartConvert();
    } else {
        ADC_StopConvert();
    }
}

/**************************************************************************************************
**  函数名称:  ST_ADC_GetValue
**  功能描述:  获取ADC值, 单位: mV
**  输入参数:  ch: 通道号, 见 ADC_CH_E
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32S DAL_ADC_GetValue(INT8U ch)
{
    if (ch < ADC_CH_MAX + 3) {
        return ((3300 * s_adcdcb.valued[ch]) >> 12);
    } else {
        return 0;
    }
}


